/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-13
 * V4.0
 */
package com.jphenix.webserver.instancea;

import com.jphenix.share.util.StringUtil;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.webserver.interfaceclass.IGlobalVar;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URLDecoder;
import java.security.Principal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 用户连接 (包含 Request Response)
 * com.jphenix.webserver.instancea.ServeConnection
 * 
 * 2019-04-16 修改了获取Content-Type值中，缺少后半部分的错误
 * 2019-04-18 修改了获取编码值错误
 * 2019-08-13 修改了报文头为标准格式（原来都是小写的）
 * 2019-08-17 修改了小写的host报文头主键导致的错误
 * 2019-09-17 整理了代码格式
 * 2019-09-20 去掉了调试打印堆栈信息
 * 2019-12-10 修改了获取报文头值报错
 * 2021-03-17 适配tomcat9中的 servlet-api.jar
 * 
 * @author 刘虻
 * 2007-3-6下午01:33:26
 */
@ClassInfo({"2021-03-17 20:55","ServeConnection"})
public class ServeConnection implements Runnable {

	protected long    lastRun;
	protected long    lastWait;
	protected String  decodeReqQuery; //未进行解码的参数字符串
	protected boolean keepAlive = true;
	
	private Socket              socket; //通信类
	private Serve               serve;  //服务类
	private ServletInputStream  in;     //输入流
	private ServletOutputStream out;    //输出流
	private Locale              locale; // = java.util.Locale.getDefault();
	private PrintWriter         pw;
	private ServletOutputStream rout;
	
	private String   resMessage;
	private String   scheme;            //母鸡
	private String   reqMethod;         // == null by default
	private String   reqUriPath;
	private String   unCodeReqUriPath;  //未进行解码的路径字符串
	private String   reqProtocol;
	private String   charEncoding;      // req and resp
	private String   remoteUser;
	private String   authType;
	private String   sessionCookieValue;
	private String   sessionUrlValue;
	private String   sessionValue;
	private String   reqQuery;
	private String[] postCache;
	
	private boolean  oneOne;            // HTTP/1.1 or better
	private boolean  reqMime;
	private boolean  headersWritten;
	
	private Vector<String>       reqHeaderNames = new Vector<String>();
	private Vector<String>       reqHeaderValues = new Vector<String>();
	private Vector<Cookie>       outCookies;
	private Vector<Cookie>       inCookies;
	private Map<String,String[]> formParameters;
	
	private int uriLen;                 //目录级次 /usr/home 为2级
	private int timesRequested;
	private int resCode = -1;

	private Hashtable<String,Object> attributes     = new Hashtable<String,Object>();
	private Hashtable<String,Object> resHeaderNames = new Hashtable<String,Object>();
	
	private Request  req  = new Request(this);
	private Response resp = new Response(this);
	
	private static final SimpleDateFormat expdatefmt       = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss 'GMT'", Locale.US);
	private static final SimpleDateFormat headerdateformat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
	
	static {
		TimeZone tz = TimeZone.getTimeZone("GMT");
		tz.setID("GMT");
		expdatefmt.setTimeZone(tz);
	}
	
	/**
	 * 返回信息类
	 * @author 马宝刚
	 * 2014年6月12日
	 */
	public class Response implements HttpServletResponse {

		private ServeConnection parent = null;  //父类
	    
	    /**
	     * 构造函数
	     * @author 马宝刚
	     */
	    public Response(ServeConnection parent) {
	        super();
	        this.parent = parent;
	    }
	    
        @Override
        public void flushBuffer() throws IOException {}

        @Override
        public int getBufferSize() {
            return 0;
        }

        @Override
        public String getCharacterEncoding() {
            return parent.getCharacterEncoding();
        }

        @Override
        public String getContentType() {
            return parent.getContentType();
        }

        @Override
        public Locale getLocale() {
            return parent.getLocale();
        }

        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            return parent.getOutputStream();
        }

        @Override
        public PrintWriter getWriter() throws IOException {
            return parent.getWriter();
        }

        @Override
        public boolean isCommitted() {
            return parent.isCommitted();
        }

        @Override
        public void reset() {
            parent.reset();
        }

        @Override
        public void resetBuffer() {
          parent.resetBuffer();
        }

        @Override
        public void setBufferSize(int arg0) {
            parent.setBufferSize(arg0);
        }

        @Override
        public void setCharacterEncoding(String arg0) {
            parent.setCharacterEncoding(arg0);
        }

        @Override
        public void setContentLength(int arg0) {
          parent.setContentLength(arg0);
        }

        @Override
        public void setContentType(String arg0) {
            parent.setContentType(arg0);
        }

        @Override
        public void setLocale(Locale arg0) {
          parent.setLocale(arg0);
        }

        @Override
        public void addCookie(Cookie arg0) {
            parent.addCookie(arg0);
        }

        @Override
        public void addDateHeader(String arg0, long arg1) {
            parent.addDateHeader(arg0,arg1);
        }

        @Override
        public void addHeader(String arg0, String arg1) {
          parent.addHeader(arg0,arg1);
        }

        @Override
        public void addIntHeader(String arg0, int arg1) {
          parent.addIntHeader(arg0,arg1);
        }

        @Override
        public boolean containsHeader(String arg0) {
          return parent.containsHeader(arg0);
        }

        @Override
        public String encodeRedirectURL(String arg0) {
          return parent.encodeRedirectURL(arg0);
        }

        @Override
        public String encodeRedirectUrl(String arg0) {
          return parent.encodeRedirectUrl(arg0);
        }

        @Override
        public String encodeURL(String arg0) {
          return parent.encodeURL(arg0);
        }

        @Override
        public String encodeUrl(String arg0) {
          return parent.encodeUrl(arg0);
        }

        @Override
        public String getHeader(String arg0) {
          return parent.getHeader(arg0);
        }

        @Override
        public Collection<String> getHeaderNames() {
          return reqHeaderNames;
        }

        @Override
        public Collection<String> getHeaders(String arg0) {
          return reqHeaderValues;
        }

        @Override
        public int getStatus() {
          return resCode;
        }

        /**
         * 覆盖方法
         * @author 刘虻
         * 2008-7-9上午02:43:39
         */
        @Override
        public void sendError(int resCode) throws IOException {
          setStatus(resCode);
          realSendError(null);
        }

        /**
         * 覆盖方法
         * @author 刘虻
         * 2008-7-9上午02:43:34
         */
        @Override
        public void sendError(int resCode, String resMessage) throws IOException {
          setStatus(resCode, resMessage);
          realSendError(null);
        }

        /**
         * 覆盖方法
         * @author 刘虻
         * 2008-6-26下午09:40:20
         */
        @Override
        public void sendRedirect(String location) throws IOException {
            if (isCommitted()) {
                //已经发送完头信息,不能再次发送头信息(包含重定向)
                throw new IllegalStateException(
                  "Can not redirect, headers have been already written");
            }
            //全路径
            if (location.indexOf(":/") < 0) { // relative
                StringBuffer portString = new StringBuffer(); //构建提交字符串
                if ("https".equalsIgnoreCase(getScheme())) {
                    if (getServerPort()!= 43) {
                        portString.append(":").append(getServerPort());
                    }
                } else if (getServerPort() != 80) {
                    portString.append(":").append(getServerPort());
                }
                if (location.length() > 0 && location.charAt(0) == '/') {
                    location = getScheme()+"://"+getServerName()+portString+location;
                    
                } else {
                    int sp = reqUriPath.lastIndexOf('/');
                    String uri;
                    if (sp < 0) {
                        uri = reqUriPath + '/';
                        sp = uri.length();
                    } else {
                        uri = reqUriPath;
                        sp++;
                    }
                    location = getScheme() + "://" + getServerName() + portString
                      + uri.substring(0, sp) + location;
                }
            }
            serve.log("Location:"+location);
            setHeader("Location", location);
            setStatus(SC_MOVED_TEMPORARILY);
            setContentType("text/html");
            StringBuffer sb = new StringBuffer(200);
            sb
                .append("<HTML><HEAD><TITLE>")
                .append(SC_MOVED_TEMPORARILY)
                .append(" Moved</TITLE></HEAD><BODY ")
                .append(IGlobalVar.BGCOLOR)
                .append("><H2>")
                .append(SC_MOVED_TEMPORARILY)
                .append(" Moved</H2>")
                .append("This document has moved <a href=")
                .append(location)
                .append(">here.<HR>");
            Identification.writeAddress(sb);
            sb.append("</BODY></HTML>");
            setContentLength(sb.length());
            // to avoid further out
            out.print(sb.toString());
            out.flush();
            out.close();
        }

        @Override
        public void setDateHeader(String arg0, long arg1) {
          parent.setDateHeader(arg0,arg1);
        }

        @Override
        public void setHeader(String arg0, String arg1) {
          parent.setHeader(arg0,arg1);
        }

        @Override
        public void setIntHeader(String arg0, int arg1) {
          parent.setIntHeader(arg0,arg1);
        }

        /**
         * 覆盖方法
         * @author 刘虻
         * 2008-7-9上午02:42:20
         */
        @Override
        public void setStatus(int resCode) {
            switch (resCode) {
            case SC_CONTINUE:
                setStatus(resCode, "Continue");
                break;
            case SC_SWITCHING_PROTOCOLS:
                setStatus(resCode, "Switching protocols");
                break;
            case SC_OK:
                setStatus(resCode, "OK");
                break;
            case SC_CREATED:
                setStatus(resCode, "Created");
                break;
            case SC_ACCEPTED:
                setStatus(resCode, "Accepted");
                break;
            case SC_NON_AUTHORITATIVE_INFORMATION:
                setStatus(resCode, "Non-authoritative");
                break;
            case SC_NO_CONTENT:
                setStatus(resCode, "No content");
                break;
            case SC_RESET_CONTENT:
                setStatus(resCode, "Reset content");
                break;
            case SC_PARTIAL_CONTENT:
                setStatus(resCode, "Partial content");
                break;
            case SC_MULTIPLE_CHOICES:
                setStatus(resCode, "Multiple choices");
                break;
            case SC_MOVED_PERMANENTLY:
                setStatus(resCode, "Moved permanentently");
                break;
            case SC_MOVED_TEMPORARILY:
                setStatus(resCode, "Moved temporarily");
                break;
            case SC_SEE_OTHER:
                setStatus(resCode, "See other");
                break;
            case SC_NOT_MODIFIED:
                setStatus(resCode, "Not modified");
                break;
            case SC_USE_PROXY:
                setStatus(resCode, "Use proxy");
                break;
            case SC_BAD_REQUEST:
                setStatus(resCode, "Bad request");
                break;
            case SC_UNAUTHORIZED:
                setStatus(resCode, "Unauthorized");
                break;
            case SC_PAYMENT_REQUIRED:
                setStatus(resCode, "Payment required");
                break;
            case SC_FORBIDDEN:
                setStatus(resCode, "Forbidden");
                break;
            case SC_NOT_FOUND:
                setStatus(resCode, "Not found");
                break;
            case SC_METHOD_NOT_ALLOWED:
                setStatus(resCode, "Method not allowed");
                break;
            case SC_NOT_ACCEPTABLE:
                setStatus(resCode, "Not acceptable");
                break;
            case SC_PROXY_AUTHENTICATION_REQUIRED:
                setStatus(resCode, "Proxy auth required");
                break;
            case SC_REQUEST_TIMEOUT:
                setStatus(resCode, "Request timeout");
                break;
            case SC_CONFLICT:
                setStatus(resCode, "Conflict");
                break;
            case SC_GONE:
                setStatus(resCode, "Gone");
                break;
            case SC_LENGTH_REQUIRED:
                setStatus(resCode, "Length required");
                break;
            case SC_PRECONDITION_FAILED:
                setStatus(resCode, "Precondition failed");
                break;
            case SC_REQUEST_ENTITY_TOO_LARGE:
                setStatus(resCode, "Request entity too large");
                break;
            case SC_REQUEST_URI_TOO_LONG:
                setStatus(resCode, "Request URI too long");
                break;
            case SC_UNSUPPORTED_MEDIA_TYPE:
                setStatus(resCode, "Unsupported media type");
                break;
            case SC_INTERNAL_SERVER_ERROR:
                setStatus(resCode, "Internal server error");
                break;
            case SC_NOT_IMPLEMENTED:
                setStatus(resCode, "Not implemented");
                break;
            case SC_BAD_GATEWAY:
                setStatus(resCode, "Bad gateway");
                break;
            case SC_SERVICE_UNAVAILABLE:
                setStatus(resCode, "Service unavailable");
                break;
            case SC_GATEWAY_TIMEOUT:
                setStatus(resCode, "Gateway timeout");
                break;
            case SC_HTTP_VERSION_NOT_SUPPORTED:
                setStatus(resCode, "HTTP version not supported");
                break;
            case 207:
                setStatus(resCode, "Multi Status");
                break;
            default:
                setStatus(resCode, "");
                break;
            }
        }

        @Override
        public void setStatus(int arg0, String arg1) {
            parent.setStatus(arg0,arg1);
        }

        @Override
        public void setContentLengthLong(long arg0) {}
	}
	
	
	/**
	 * 页面请求处理类
	 * @author 马宝刚
	 * 2014年6月12日
	 */
	public class Request implements HttpServletRequest {

	    //父类
      protected ServeConnection parent = null;

        /**
         * 构造函数
         * @author 马宝刚
         */
        public Request(ServeConnection parent) {
            super();
            this.parent = parent;
        }

        /**
         * 当前请求是否为内部Web服务相应
         * @return 当前请求是否为内部Web服务相应
         * 2017年8月31日
         * @author MBG
         */
        public boolean isNativeServ() {
          if(serve!=null) {
            return serve.isNativeServ;
          }
          return false;
        }

        @Override
        public AsyncContext getAsyncContext() {
            return null;
        }

        @Override
        public Object getAttribute(String arg0) {
            return parent.getAttribute(arg0);
        }

        @Override
        public Enumeration<String> getAttributeNames() {
            return parent.getAttributeNames();
        }

        @Override
        public String getCharacterEncoding() {
            return parent.getCharacterEncoding();
        }

        @Override
        public int getContentLength() {
            return parent.getContentLength();
        }

        @Override
        public String getContentType() {
            return parent.getContentType();
        }

        @Override
        public DispatcherType getDispatcherType() {
            return null;
        }

        @Override
        public ServletInputStream getInputStream() throws IOException {
            return parent.getInputStream();
        }

        @Override
        public String getLocalAddr() {
            return parent.getLocalAddr();
        }

        @Override
        public String getLocalName() {
            return parent.getLocalName();
        }

        @Override
        public int getLocalPort() {
            return parent.getLocalPort();
        }

        @Override
        public Locale getLocale() {
            return parent.getLocale();
        }

        @Override
        public Enumeration<Locale> getLocales() {
            return parent.getLocales();
        }

        @Override
        public String getParameter(String arg0) {
            return parent.getParameter(arg0);
        }

        @Override
        public Map<String, String[]> getParameterMap() {
            return parent.getParameterMap();
        }

        @Override
        public Enumeration<String> getParameterNames() {
            return parent.getParameterNames();
        }

        @Override
        public String[] getParameterValues(String arg0) {
            return parent.getParameterValues(arg0);
        }

        @Override
        public String getProtocol() {
            return parent.getProtocol();
        }

        @Override
        public BufferedReader getReader() throws IOException {
            return parent.getReader();
        }

        @Override
        public String getRealPath(String arg0) {
            return parent.getRealPath(arg0);
        }

        @Override
        public String getRemoteAddr() {
            return parent.getRemoteAddr();
        }

        @Override
        public String getRemoteHost() {
            return parent.getRemoteHost();
        }

        @Override
        public int getRemotePort() {
            return parent.getRemotePort();
        }

        @Override
        public RequestDispatcher getRequestDispatcher(String arg0) {
            return parent.getRequestDispatcher(arg0);
        }

        @Override
        public String getScheme() {
            return parent.getScheme();
        }

        @Override
        public String getServerName() {
            return parent.getServerName();
        }

        @Override
        public int getServerPort() {
            return parent.getServerPort();
        }

        @Override
        public ServletContext getServletContext() {
            return null;
        }

        @Override
        public boolean isAsyncStarted() {
            return false;
        }

        @Override
        public boolean isAsyncSupported() {
            return false;
        }

        @Override
        public boolean isSecure() {
            return false;
        }

        @Override
        public void removeAttribute(String arg0) {
            parent.removeAttribute(arg0);
        }

        @Override
        public void setAttribute(String arg0, Object arg1) {
            parent.setAttribute(arg0,arg1);
        }

        @Override
        public void setCharacterEncoding(String arg0)
                throws UnsupportedEncodingException {
            parent.setCharacterEncoding(arg0);
        }

        @Override
        public AsyncContext startAsync() {
            return null;
        }

        @Override
        public AsyncContext startAsync(ServletRequest arg0, ServletResponse arg1) {
            return null;
        }

        @Override
        public boolean authenticate(HttpServletResponse arg0)
                throws IOException, ServletException {
            return false;
        }

        @Override
        public String getAuthType() {
            return parent.getAuthType();
        }

        @Override
        public String getContextPath() {
            return parent.getContextPath();
        }

        @Override
        public Cookie[] getCookies() {
            return parent.getCookies();
        }

        @Override
        public long getDateHeader(String arg0) {
            return parent.getDateHeader(arg0);
        }

        @Override
        public String getHeader(String arg0) {
            return parent.getHeader(arg0);
        }

        @Override
        public Enumeration<String> getHeaderNames() {
            return new Enumeration<String>() {
                int point = 0;
                @Override
                public boolean hasMoreElements() {
                    return point < reqHeaderNames.size();
                }

                @Override
                public String nextElement() {
                    return reqHeaderNames.get(point++);
                }
                
            };
        }

        @Override
        public Enumeration<String> getHeaders(String arg0) {
            return null;
        }

        @Override
        public int getIntHeader(String arg0) {
            return parent.getIntHeader(arg0);
        }

        @Override
        public String getMethod() {
            return parent.getMethod();
        }

        @Override
        public Part getPart(String arg0) throws IOException,
                IllegalStateException, ServletException {
            return null;
        }

        @Override
        public Collection<Part> getParts() throws IOException,
                IllegalStateException, ServletException {
            return null;
        }

        @Override
        public String getPathInfo() {
            return parent.getPathInfo();
        }

        @Override
        public String getPathTranslated() {
            return parent.getPathTranslated();
        }

        @Override
        public String getQueryString() {
            return parent.getQueryString();
        }

        @Override
        public String getRemoteUser() {
            return parent.getRemoteUser();
        }

        @Override
        public String getRequestURI() {
            return parent.getRequestURI();
        }

        @Override
        public StringBuffer getRequestURL() {
            return parent.getRequestURL();
        }

        @Override
        public String getRequestedSessionId() {
            return parent.getRequestedSessionId();
        }

        @Override
        public String getServletPath() {
            return parent.getServletPath();
        }

        @Override
        public HttpSession getSession() {
            return parent.getSession();
        }

        @Override
        public HttpSession getSession(boolean arg0) {
            return parent.getSession(arg0);
        }

        @Override
        public Principal getUserPrincipal() {
            return parent.getUserPrincipal();
        }

        @Override
        public boolean isRequestedSessionIdFromCookie() {
            return parent.isRequestedSessionIdFromCookie();
        }

        @Override
        public boolean isRequestedSessionIdFromURL() {
            return parent.isRequestedSessionIdFromURL();
        }

        @Override
        public boolean isRequestedSessionIdFromUrl() {
            return parent.isRequestedSessionIdFromUrl();
        }

        @Override
        public boolean isRequestedSessionIdValid() {
            return parent.isRequestedSessionIdValid();
        }

        @Override
        public boolean isUserInRole(String arg0) {
            return parent.isUserInRole(arg0);
        }

        @Override
        public void login(String arg0, String arg1) throws ServletException {}

        @Override
        public void logout() throws ServletException {}

        @Override
        public long getContentLengthLong() {
          return 0;
        }

        @Override
        public String changeSessionId() {
          return null;
        }

        @Override
        public <T extends HttpUpgradeHandler> T upgrade(Class<T> arg0) throws IOException, ServletException {
          return null;
        }
	}
	
	/**
	 * 构造函数
	 * 2008-7-9上午02:31:02
	 */
	public ServeConnection(Socket socket, Serve serve) {
		// Save arguments.
		this.socket = socket;
		this.serve = serve;

		if (serve.getKeepAliveCleaner() != null) {
			serve.getKeepAliveCleaner().addConnection(this);
		}

		// Start a separate thread to read and handle the request.
		try {
			serve.getThreadManager().executeThread(this);
		}catch(Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取通信类
	 * @author 刘虻
	 * 2008-7-9上午02:31:07
	 * @return 通信类
	 */
	public Socket getSocket() {
		return this.socket;
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:31:25
	 */
    protected void restart() {
        //线程
        Thread cThread = Thread.currentThread();
        cThread.setName("free action ["+cThread.getName()+"]");
		reqMethod = null;
		reqUriPath = null;
		reqProtocol = null;
		charEncoding = null;
		remoteUser = null;
		authType = null;
		oneOne = false;
		reqMime = false;
		// considering that clear() works faster than new
		if (reqHeaderNames == null) {
            reqHeaderNames = new Vector<String>();
        } else {
            reqHeaderNames.clear();
        }
		if (reqHeaderValues == null) {
            reqHeaderValues = new Vector<String>();
        } else {
            reqHeaderValues.clear();
        }
		locale = null;
		uriLen = 0;
		outCookies = null;
		inCookies = null;
		sessionCookieValue = null;
		sessionUrlValue = null;
		sessionValue = null;
		reqQuery = null;
		pw = null;
		rout = null;
		formParameters = null;
		if (attributes == null) {
            attributes = new Hashtable<String, Object>();
        } else {
            attributes.clear();
        }
		resCode = -1;
		resMessage = null;
		resHeaderNames.clear();
		headersWritten = false;
		postCache = null;
		((ServeInputStream) in).refresh();
		((ServeOutputStream) out).refresh();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:31:40
	 */
    @Override
    public void run() {
		try {
			in = new ServeInputStream(socket.getInputStream());
			out = new ServeOutputStream(socket.getOutputStream(), this);
			do {
				restart();
				// Get the streams.
				parseRequest();

				// consider caching socket stuff for faster logging
				serve.log(socket.getInetAddress().toString()
						+ ':'
						+ socket.getLocalPort()
						+ ' '
						+ reqMethod
						+ ' '
						+ reqUriPath
						+ ' '
						+ resCode
						+ "|"
						+ getHeader("Referer")
						+ "|"
						+ getHeader("User-Agent"));
			
				lastRun = 0;
				timesRequested++;
			} while (keepAlive && serve.isKeepAlive()
					&& timesRequested < serve.getMaxTimesConnectionUse());
		} catch (IOException ioe) {
			serve.log(ioe.getMessage());
		} finally {
			try {
				socket.close();
			} catch (IOException e) { /* ignore */
			}
		}
	}

	
	/**
	 * 解析用户提交请求
	 * @author 刘虻
	 * 2008-2-20下午02:22:20
	 * @throws IOException 之星发生异常
	 */
	@SuppressWarnings("deprecation")
    protected void parseRequest() throws IOException {
		
		byte[] lineBytes = new byte[4096];
		int len;
		String line;
		lastWait = System.currentTimeMillis();
		// Read the first line of the request.
		len = in.readLine(lineBytes, 0, lineBytes.length);
		if (len == -1 || len == 0) {
			if (keepAlive) {
                throw new IOException("Inconsistent input data");
            } else {
				problem("Status-Code 400: Bad Request(empty)",null, Response.SC_BAD_REQUEST);
				return;
			}
		}
		if (len >= lineBytes.length) {
			problem("Status-Code 414: Request-URI Too Long",null,
					Response.SC_REQUEST_URI_TOO_LONG);
			return;
		}
		line = new String(lineBytes, 0, len);
		StringTokenizer ust = new StringTokenizer(line);
		reqProtocol = null;
		if (ust.hasMoreTokens()) {
			reqMethod = ust.nextToken();
			if (ust.hasMoreTokens()) {
				reqUriPath = ust.nextToken();
				if (reqUriPath!=null) {
					//保留原有编码格式,待setCharacterEncoding可以重新进行编码
					unCodeReqUriPath = reqUriPath;
					if(getCharacterEncoding()!=null) {
						reqUriPath = new String(reqUriPath.getBytes(),getCharacterEncoding());
					}
					Thread.currentThread().setName(reqUriPath);
				}
				int uop = reqUriPath.indexOf(IGlobalVar.SESSION_URL_NAME);
				if (uop > 0) {
					sessionUrlValue = reqUriPath.substring(uop
							+ IGlobalVar.SESSION_URL_NAME.length());
					reqUriPath = reqUriPath.substring(0, uop);
					try {
						serve.getSession(sessionUrlValue).userTouch();
					} catch (NullPointerException npe) {
						sessionUrlValue = null;
					} catch (IllegalStateException ise) {
						sessionUrlValue = null;
					}
				}
				if (ust.hasMoreTokens()) {
					reqProtocol = ust.nextToken();
					oneOne = !"HTTP/1.0".equals(reqProtocol.toUpperCase());
					reqMime = true;
					// Read the rest of the lines.
					String s;
					String key;
					String value;
					String charset;
					while ((s = ((ServeInputStream) in).readLine()) != null) {
						if (s.length() == 0) {
                            break;
                        }
						int c = s.indexOf(':');
						if (c > 0) {
							//.toLowerCase()原本key在这里做了强制小写，但这不符合HTTP规范，所以去掉强制小写
							key   = s.substring(0, c).trim();
							value = s.substring(c + 1).trim();
							if(IGlobalVar.CONTENTTYPE.equalsIgnoreCase(key)) {
								//有的浏览器会提交 application/x-www-form-urlencoded; charset=UTF-8
								//IE浏览器会提交  application/x-www-form-urlencoded
								int point = value.indexOf(";"); //分隔符
								if(point>-1) {
									//提交内容编码
									charset = value.substring(point+1).trim();
									
									//注意：在Tomat中测试  遇到 application/x-www-form-urlencoded; charset=UTF-8 这种情况，并不把后面的charset=UTF-8截取掉
									//      另外在form上传文件时Content-Type需要返回 multipart/form-data; boundary=----WebKitFormBoundaryUskssGJa3IAjlq7I 而不是前半部分
									//value = value.substring(0,point).trim();
									
									point = charset.indexOf("=");
									if(point>-1) {
										charset = charset.substring(point+1).trim();
										setCharacterEncoding(charset);
									}
								}
							} else if (IGlobalVar.CONNECTION.equalsIgnoreCase(key)) {
								//因为是轻量级框架，没有设计在输出HTML时获取报文体长度content-length
								//因为如果要获取报文体长度的话，必须缓存所有报文体，然后计算出长度
								//写入报文头，然后输出报文体，这个相对复杂，也耗资源
								//Http1.0 中，如果Connection:keep-alive 则需要在报文头
								//中包含报文体长度，否则做Post后，页面会无响应
								//在做Get时，经过servlet处理后的内容也会混乱
								//所以在Http1.0时，就自动设置为不保持连接
								//目前浏览器都是用的Http1.1，很少会用到Http1.0
								//但也会用到，比如浏览器设置了代理访问时，浏览器设置的高级选项中
								//没有勾选通过代理访问 Http1.1就会出现问题
								if(!oneOne) {
									keepAlive = false;
								}
								//以下是原代码
//								if (oneOne)
//									keepAlive = "close".equalsIgnoreCase(value) == false;
//								else
//									keepAlive = IGlobalVar.KEEPALIVE
//											.equalsIgnoreCase(value);
							}
							reqHeaderNames.addElement(key);
							reqHeaderValues.addElement(value);
						} else {
							serve.log("header field '" + s + "' without ':'");
						}
					}
				} else {
					reqProtocol = "HTTP/0.9";
					oneOne = false;
					reqMime = false;
				}
			}
		}
		if (reqProtocol == null) {
			problem("Malformed request line",null, Response.SC_BAD_REQUEST);
			return;
		}
		// Check Host: header in HTTP/1.1 requests.
		if (oneOne) {
			String host = getHeader(IGlobalVar.HOST);
			if (host == null) {
				problem("'Host' header missing on HTTP/1.1 request",null,
						Response.SC_BAD_REQUEST);
				return;
			}
		}
		if (serve.getContextPathLength()>0 
				&& !reqUriPath.startsWith(serve.getContextPath())) {
			resp.sendError(HttpServletResponse.SC_NOT_FOUND);
			return;
		}
		// Split off query string, if any.
		int qmark = reqUriPath.indexOf('?');
		if (qmark > -1) {
			reqQuery = reqUriPath.substring(qmark + 1);
			if(getCharacterEncoding()==null) {
			    try {
			        reqUriPath = URLDecoder.decode(reqUriPath.substring(0, qmark));
			    }catch(Exception e) {
			        reqUriPath = reqUriPath.substring(0, qmark);
			    }
			}else {
			    try {
			        reqUriPath = URLDecoder.decode(reqUriPath.substring(0, qmark),getCharacterEncoding());
			    }catch(Exception e) {
			        reqUriPath = reqUriPath.substring(0, qmark);
			    }
			}
		} else {
		    try {
		          if(getCharacterEncoding()==null) {
		                reqUriPath = URLDecoder.decode(reqUriPath);
		            }else {
		                reqUriPath = URLDecoder.decode(reqUriPath,getCharacterEncoding());
		            }
		    }catch(Exception e) {}
		}
		if (IGlobalVar.CHUNKED.equals(getHeader(IGlobalVar.TRANSFERENCODING))) {
			setHeader(IGlobalVar.CONTENTLENGTH, null);
			((ServeInputStream) in).chunking(true);
		}
		//获取内容大小
		String contentLength = getHeader(IGlobalVar.CONTENTLENGTH);
		if (contentLength != null) {
            try {
                ((ServeInputStream) in).setContentLength(Long
                        .parseLong(contentLength));
            } catch (NumberFormatException nfe) {
                serve.log("Invalid value of input content-length: "
                        + contentLength);
            }
        }
		if (keepAlive && serve.isKeepAlive()) {
			if (socket.getKeepAlive() == false) {
                socket.setKeepAlive(true);
            }
			// getParameterNames(); // can be mandatory to read post stream when a servlet didn't request parameters or not found
			// socket.setSoTimeout(0);
			if (reqMime) {
				setHeader(IGlobalVar.CONNECTION, IGlobalVar.KEEPALIVE); // set for 1.1 too, because some client do not follow a standard
				if (oneOne) {
                    setHeader(IGlobalVar.KEEPALIVE, serve
                            .getKeepAliveParamStr());
                }
			}
		} else {
			setHeader(IGlobalVar.CONNECTION, "close");
		}
		if (reqMime) {
			setHeader("MIME-Version", "1.0");
		}
		
		//检测路径是否为文件夹路径，如果是文件夹路径，则尝试显示默认文件
		reqUriPath = checkUriPath(reqUriPath);
		
		String extName = ""; //扩展名
		String chekUri = null; //用于检测用的路径
		uriLen = reqUriPath.indexOf("."); //扩展名分割点
		if (uriLen>-1) {
			extName = reqUriPath.substring(uriLen+1);
			chekUri = reqUriPath.substring(0,uriLen);
		}else {
			chekUri = reqUriPath;
			uriLen = reqUriPath.length();
		}
		//获取指定Servlet
		HttpServlet os = serve.getRegistry().get(chekUri,extName);
		if (os!=null) { // note, os always not null
			lastRun = System.currentTimeMillis();
			// System.err.println("Servlet "+os[0]+" for path "+reqUriPath);
			runServlet(os);
		} else {
			problem("No any servlet found for serving " + reqUriPath,null,
					Response.SC_BAD_REQUEST);
		}
		skipPostData(); // if any
	}
	
	
	/**
	 * 检测路径是否为文件夹路径，如果是，则尝试访问默认文件
	 * @author 刘虻
	 * 2010-1-19下午06:00:48
	 * @param uriPath 检测路径
	 * @return 整理后的路径
	 */
	protected String checkUriPath(String uriPath) {
		//检测路径是否为文件夹路径
		String allPath = getRealPath(uriPath);
		if(!allPath.endsWith("/")) {
			allPath += "/";
		}
		File cFile = new File(allPath);
		if(cFile.exists() && cFile.isDirectory()) {
		    File wFile; //默认文件
			for(int i=0;i<serve.getWelcomeFilePages().length;i++) {
				//检测默认文件是否存在
				wFile = new File(allPath+serve.getWelcomeFilePages()[i]);
				if(wFile.exists() && wFile.isFile()) {
					if(uriPath.endsWith("/")) {
						return uriPath+serve.getWelcomeFilePages()[i];
					}
					return uriPath+"/"+serve.getWelcomeFilePages()[i];
				}
			}
		}
		return uriPath;
	}

	
	/**
	 * 运行服务程序
	 * @author 刘虻
	 * 2008-2-20下午02:24:19
	 * @param servlete
	 */
	protected void runServlet(HttpServlet servlet) {
		// Set default response fields.
		resp.setStatus(Response.SC_OK);
		setDateHeader("Date", System.currentTimeMillis());
		setHeader("Server", IGlobalVar.SERVER_NAME + "/"
				+ IGlobalVar.SERVER_VERSION);
		try {
			parseCookies(); //解析Cookies
			if (sessionValue == null) { // not from cookie
				sessionValue = sessionUrlValue;
			}
			//通过过滤器链调用Servlet
			(new FilterChainImpl(serve.getFilterList(),servlet)).doFilter(req,resp);
			if (pw != null) {
				pw.flush();
			}
			out.flush();
			out.close();
			// } // ???
		} catch (IOException e) {
			serve.log("IO problem running servlet", e);
			problem("IO problem running servlet: " + e.toString(),e,
					Response.SC_BAD_REQUEST);
		} catch (UnavailableException e) {
			if (e.isPermanent()) {
				serve.getRegistry().remove(servlet);
				servlet.destroy();
			} else if (e.getUnavailableSeconds() > 0) {
                serve.log("Unsupported temporary unavailability  "+servlet);
            }
			problem(e.getMessage(),e, Response.SC_SERVICE_UNAVAILABLE);
		} catch (ServletException e) {
			serve.log("Servlet exception", e);
			Throwable rootCause = e.getRootCause();
			while (rootCause != null) {
				serve.log("Caused by", rootCause);
				if (rootCause instanceof ServletException) {
                    rootCause = ((ServletException) rootCause).getRootCause();
                } else {
                    rootCause = rootCause.getCause();
                }
			}
			problem(e.toString(),e, Response.SC_INTERNAL_SERVER_ERROR);
		} catch (Exception e) {
			serve.log("Unexpected problem running servlet", e);
			problem("Unexpected problem running servlet: " +e,e,
					Response.SC_INTERNAL_SERVER_ERROR);
		}
	}

	/**
	 * 出现问题
	 * @author 刘虻
	 * 2008-7-9上午02:31:57
	 * @param logMessage 母鸡
	 * @param resCode 母鸡
	 */
	protected void problem(String message,Exception e, int resCode) {
		serve.log(message+((e==null)?"":getExceptionInfo(e)));
		try {
			setStatus(resCode, message);
			realSendError(e);
		} catch (IllegalStateException se) { /* ignore */
		} catch (IOException ioe) { /* ignore */
		}
	}
	
	
	
    /**
     * 获取异常信息，输出字符串
     * 刘虻
     * 2013-3-19 下午3:05:30
     * @param e 异常对象
     * @param enterStr 换行符
     * @return 异常信息
     */
    protected String getExceptionInfo(Throwable e) {
    	if(e==null) {
    		return "";
    	}
    	//构建返回值
    	StringBuffer reSbf = new StringBuffer("\n");
    	reSbf.append(e).append("\n");
    	//堆栈
    	StackTraceElement[] eles = e.getStackTrace();
    	if(eles!=null) {
    		for(int i=0;i<eles.length;i++) {
    			reSbf.append(eles[i]).append("\n");
    		}
    	}
    	return reSbf.toString();
    }

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:32:07
	 * @param str 母鸡
	 * @return 母鸡
	 */
	public String decode(String str) {
		StringBuffer result = new StringBuffer();
		int l = str.length();
		for (int i = 0; i < l; ++i) {
			char c = str.charAt(i);
			if (c == '%' && i + 2 < l) {
				char c1 = str.charAt(i + 1);
				char c2 = str.charAt(i + 2);
				if (isHexit(c1) && isHexit(c2)) {
					result.append((char) (hexit(c1) * 16 + hexit(c2)));
					i += 2;
				} else {
                    result.append(c);
                }
			} else if (c == '+') {
                result.append(' ');
            } else {
                result.append(c);
            }
		}
		return result.toString();
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:32:15
	 * @param c 母鸡
	 * @return 母鸡
	 */
	protected boolean isHexit(char c) {
		String legalChars = "0123456789abcdefABCDEF";
		return (legalChars.indexOf(c) != -1);
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:32:21
	 * @param c 母鸡
	 * @return 母鸡
	 */
	protected int hexit(char c) {
		if (c >= '0' && c <= '9') {
            return c - '0';
        }
		if (c >= 'a' && c <= 'f') {
            return c - 'a' + 10;
        }
		if (c >= 'A' && c <= 'F') {
            return c - 'A' + 10;
        }
		return 0; // shouldn't happen, we're guarded by isHexit()
	}

	/**
	 * 解析Cookies
	 * @author 刘虻
	 * 2008-6-28下午07:23:44
	 * @deprecated
	 */
	protected void parseCookies() {
		if (inCookies == null) {
            inCookies = new Vector<Cookie>();
        }
		try {
			String cookie_name;
			String cookie_value;
			String cookie_path;
			String cookies = getHeader(IGlobalVar.COOKIE);
			if (cookies == null) {
                return;
            }
			// Enumeration e = getHeaders(COOKIE);
			// while(e.hasMoreElements())
			// cookies += (String)e.nextElement();
			StringTokenizer st = new StringTokenizer(cookies, ";", true);
			while (st.hasMoreTokens()) {
				StringTokenizer st2 = new StringTokenizer(st.nextToken(), "=");
				if (st2.hasMoreTokens()) {
					cookie_name = st2.nextToken().trim();
					if (st2.hasMoreTokens()) {
						cookie_value = st2.nextToken(",").trim();
						if (cookie_value.length() > 0
								&& cookie_value.charAt(0) == '=') {
                            cookie_value = cookie_value.substring(1);
                        }
						cookie_path = "/";
						while (st2.hasMoreTokens()) {
							String cookie_atr = st2.nextToken();
							if ("$Version".equalsIgnoreCase(cookie_atr)
									|| "$Path".equalsIgnoreCase(cookie_atr)
									|| "$Domain".equalsIgnoreCase(cookie_atr)) {
								continue;
							}
							cookie_path = cookie_atr;
						}
						Cookie cookie = new Cookie(cookie_name, cookie_value);
						// System.err.println("Cookie
						// set:"+cookie_name+':'+cookie_value);
						cookie.setPath(cookie_path);
						inCookies.addElement(cookie);
						if (serve.getSessionCookieName().equals(cookie_name)
								&& sessionCookieValue == null) {
							sessionCookieValue = cookie_value;
							try {
								serve.getSession(sessionCookieValue)
										.userTouch();
								sessionValue = sessionCookieValue;
								sessionUrlValue = null;
							} catch (IllegalStateException ise) {
								sessionCookieValue = null;
							} catch (NullPointerException npe) {
								sessionCookieValue = null;
							}
						}
					}
				}
			}
		} catch (Throwable e) {
			serve.log("prepareCookies(): ", e);
		}
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:32:41
	 */
	public int getContentLength() {
		return getIntHeader(IGlobalVar.CONTENTLENGTH);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:32:46
	 */
	public String getContentType() {
		return getHeader(IGlobalVar.CONTENTTYPE);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:32:51
	 */
	public String getProtocol() {
		return reqProtocol;
	}

	
	/**
	 * "http", "https", or "ftp"
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:33:10
	 */
	public String getScheme() {
		if (scheme == null)
			// lazy stuf dlc
        {
            synchronized (this) {
                if (scheme == null) {
                    scheme = socket.getClass().getName().indexOf("SSLSocket") > 0 ? "https"
                            : "http";
                }
            }
        }
		return scheme;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:33:21
	 */
	public String getServerName() {
		String serverName;
		serverName = getHeader(IGlobalVar.HOST);
		if (serverName != null && serverName.length() > 0) {
			int colon = serverName.indexOf(':');
			if (colon >= 0) {
				if (colon < serverName.length()) {
                    serverName = serverName.substring(0, colon);
                }
			}
		}

		if (serverName == null) {
			try {
				serverName = InetAddress.getLocalHost().getHostName();
			} catch (java.net.UnknownHostException ignore) {
				serverName = "127.0.0.0";
			}
		}

		int slash = serverName.indexOf("/");
		if (slash >= 0) {
            serverName = serverName.substring(slash + 1);
        }
		return serverName;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:33:29
	 */
	public int getServerPort() {
		return socket.getLocalPort();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:33:34
	 */
	public String getRemoteAddr() {
		return socket.getInetAddress().getHostAddress();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:34:40
	 */
	public String getRemoteHost() {
		String result = socket.getInetAddress().getHostName();
		return result != null ? result : getRemoteAddr();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:34:50
	 */
	public String getRealPath(String path) {
		return serve.getRealPath(path);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:34:56
	 */
	public ServletInputStream getInputStream() throws IOException {
		synchronized (in) {
			if (((ServeInputStream) in).isReturnedAsReader()) {
				throw new IllegalStateException("Already returned as a reader.");
			}
			((ServeInputStream) in).setReturnedAsReader(true);
		}
		return in;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:35:01
	 */
	public BufferedReader getReader() {
		synchronized (in) {
			if (((ServeInputStream) in).isReturnedAsStream()) {
				throw new IllegalStateException("Already returned as a stream.");
			}
		}
		try {
			return new BufferedReader(new InputStreamReader(in,getServCharEncoding()));
		} catch (UnsupportedEncodingException uee) {}
		return new BufferedReader(new InputStreamReader(in));
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:35:05
	 */
	protected void skipPostData() {
		if (postCache == null && "POST".equals(reqMethod)) {
			if((((ServeInputStream) in).isReturnedAsReader())) {
				//如果用户在应用程序中使用了getInputStream()读取过了信息，就不用执行这步了
				return;
			}
			InputStream is = null;
			int len = getContentLength();
			try {
				is = getInputStream();
				while (len > 0) {
					long r = is.skip(len);
					if (r > 0) {
                        len -= r;
                    } else {
                        break;
                    }
				}
			} catch (IOException ex) {
				serve.log("IOException " + ex
						+ " at skipping 'POST' data of length " + len);
			} finally {
				if (is != null) {
                    try {
                        is.close();
                    } catch (IOException ioe) {
                    }
                }
			}
		}
	}
	
	/**
	 * 获取系统编码
	 * @author 刘虻
	 * 2010-1-20下午02:36:29
	 * @return 系统编码
	 */
	protected String getServCharEncoding() {
		if(charEncoding==null) {
			charEncoding = 
				serve.getServeParameter()
					.getArgumentString(IGlobalVar.ARG_SERVLET_TRANSFER_ENCODING);
			if(charEncoding==null || charEncoding.length()<1) {
				//charEncoding = System.getProperty("file.encoding");
				charEncoding = "UTF-8"; //使用固定的UTF-8编码
			}
		}
		return charEncoding;
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:35:22
	 * @return
	 */
	protected synchronized Map<String,String[]> getParametersFromRequest() {
		//构造返回值
		Map<String,String[]> result = new Hashtable<String,String[]>();
		if ("GET".equals(reqMethod)) {
			if (reqQuery != null) {
                try {
                    parseQueryString(result,reqQuery,getServCharEncoding());
                } catch (IllegalArgumentException ex) {
                    serve.log("Exception " + ex + " at parsing 'get' data "
                            + reqQuery);
                }
            }
		} else if ("POST".equals(reqMethod)) {
			if (reqQuery != null && reqQuery.length() > 0) {
				try {
					parseQueryString(result,reqQuery,getServCharEncoding());
				}catch(Exception e) {}
			}
			if (postCache == null) {
				postCache = new String[1];
				InputStream is = null;
				try {
					parsePostData(result,getContentLength(),
							is = getInputStream(), getServCharEncoding(), postCache);
				} catch (Exception ex) {
					serve.log("Exception " + ex
							+ " at parsing 'POST' data of length "
							+ getContentLength());
				} finally {
					if (is != null) {
                        try {
                            is.close();
                        } catch (IOException ioe) {
                        }
                    }
				}
			} else {
				parseQueryString(result,postCache[0],getServCharEncoding());
			}
		}
		return result;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:35:35
	 */
	public synchronized Enumeration<String> getParameterNames() {
		if (formParameters == null) {
			formParameters = getParametersFromRequest();
		}
		return ((Hashtable<String,?>) formParameters).keys();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:35:47
	 */
	public String getParameter(String name) {
		String[] params = getParameterValues(name);
		if (params == null || params.length == 0) {
            return null;
        }

		return params[0];
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:35:57
	 */
	public synchronized String[] getParameterValues(String name) {
		if (formParameters == null) {
            getParameterNames();
        }

		return formParameters.get(name);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:04
	 */
	public Object getAttribute(String name) {
		// System.err.println("!!!Get att orig:"+name+"="+attributes.get(name));
		return attributes.get(name);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:09
	 */
	public Cookie[] getCookies() {
		Cookie[] cookieArray = new Cookie[inCookies.size()];
		inCookies.copyInto(cookieArray);
		return cookieArray;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:15
	 */
	public String getMethod() {
		return reqMethod;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:24
	 */
	public String getRequestURI() {
		return reqUriPath;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:31
	 */
	public StringBuffer getRequestURL() {
		//获取主机地址
		String host = getHeader("Host");
		String scheme = getScheme(); //协议名
		if(host==null || host.length()<1) {
			int port = getServerPort();
			if(!("http".equals(scheme) && port==80) || ("https".equals(scheme) && port==443) ) {
				host = getLocalAddr()+":"+port;
			}
		}
		//因为Tomcat 和 WebLogic 都不返回带参数的URL，所以这里也取消参数字符串
//		return new StringBuffer().append(getScheme()).append("://").append(host).append(getRequestURI())
//				.append((reqQuery==null || reqQuery.length()<1)?"":"?"+reqQuery);
		return new StringBuffer().append(getScheme()).append("://").append(host).append(getRequestURI());
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:44
	 */
	public String getServletPath() {
		//构建返回值
		//String rePath = uriLen > 0 ? reqUriPath.substring(0, uriLen) : "";
		String rePath = reqUriPath;
		if (rePath.startsWith(serve.getContextPath())) {
			return rePath.substring(serve.getContextPathLength());
		}
		return rePath;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:53
	 */
	public String getPathInfo() {
		// In this server, the entire path is regexp-matched against the
		// servlet pattern, so there's no good way to distinguish which
		// part refers to the servlet.
//		return uriLen >= reqUriPath.length() ? reqUriPath : reqUriPath
//				.substring(uriLen);
		return reqUriPath;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:06
	 */
	public String getPathTranslated() {
		// In this server, the entire path is regexp-matched against the
		// servlet pattern, so there's no good way to distinguish which
		// part refers to the servlet.
		return getRealPath(getPathInfo());
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:12
	 */
	public String getQueryString() {
		return reqQuery;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:18
	 */
	public String getRemoteUser() {
		return remoteUser;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:25
	 */
	public String getAuthType() {
		return authType;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:30
	 */
	public String getHeader(String name) {
		int i = reqHeaderNames.indexOf(name);
		if (i == -1) {
            return null;
        }
		return reqHeaderValues.elementAt(i);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:34
	 */
	public int getIntHeader(String name) {
		String val = getHeader(name);
		if (val == null) {
            return -1;
        }
		return Integer.parseInt(val);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:37
	 */
	public long getDateHeader(String name) {
		String val = getHeader(name);
		if (val == null) {
            return -1;
        }
		try {
			return headerdateformat.parse(val).getTime();
		} catch (Exception e) {
			throw new IllegalArgumentException("Value " + val
					+ " can't be converted to Date using "
					+ headerdateformat.toPattern());
		}
	}




	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:51
	 * @deprecated
	 */
	public synchronized HttpSession getSession(boolean create) {
		HttpSession result = null;
		if (sessionValue != null) {
			result = serve.getSession(sessionValue);
			if (result != null && ((Session) result).isValid() == false) {
				serve.removeSession(sessionValue);
				result = null;
			}
		}
		if (result == null && create) {
			result = serve.createSession();
			if (result != null) {
				sessionValue = result.getId();
			}
		}
		return result;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:57
	 */
	public HttpSession getSession() {
		return getSession(true);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:59
	 */
	public boolean isRequestedSessionIdFromURL() {
		return false;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:05
	 */
	public Enumeration<String> getAttributeNames() {
		return attributes.keys();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:08
	 */
	public void setAttribute(String key, Object o) {
		// System.err.println("!!!Set att orig:"+key+"="+o);
		if (o != null) {
            attributes.put(key, o);
        } else {
            attributes.remove(key);
        }
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:14
	 */
	public String getRequestedSessionId() {
		return sessionValue;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:18
	 * @deprecated
	 */
	public boolean isRequestedSessionIdValid() {
		if (sessionValue != null) {
			Session session = serve.getSession(sessionValue);
			return (session != null && session.isValid());
		}
		return false;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:23
	 */
	public boolean isRequestedSessionIdFromCookie() {
		return sessionCookieValue != null;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:31
	 */
	public boolean isRequestedSessionIdFromUrl() {
		return sessionUrlValue != null;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:35
	 */
	public void setContentLength(int length) {
		setIntHeader(IGlobalVar.CONTENTLENGTH, length);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:43
	 */
	public void setContentType(String type) {
		setHeader(IGlobalVar.CONTENTTYPE, type != null ? type : "Unknown");
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:48
	 */
	public ServletOutputStream getOutputStream() {
		synchronized (out) {
			if (rout == null) {
				if (pw != null) {
                    throw new IllegalStateException(
                            "Already returned as a writer");
                }
				rout = out;
			}
		}
		return rout;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:54
	 */
	public PrintWriter getWriter() throws IOException {
		synchronized (out) {
			if (pw == null) {
				if (rout != null) {
                    throw new IllegalStateException(
                            "Already was returned as servlet output stream");
                }
				String encoding = getCharacterEncoding();
				if (encoding != null) {
                    pw = new PrintWriter(new OutputStreamWriter(out, encoding));
                } else {
                    pw = new PrintWriter(out);
                }
			}
		}
		return pw;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:59
	 */
	public String getCharacterEncoding() {
		Object value = resHeaderNames.get(IGlobalVar.CONTENTTYPE);
		String ct = null;
		if(value!=null) {
		    if(value instanceof String[]) {
		        if(((String[])value).length>0) {
		            ct = ((String[])value)[0];
		        }else {
		            ct = (String)value;
		        }
		    }else {
		    	ct = value.toString();
		    }
		}
		if (ct != null) {
			int scp = ct.indexOf(';');
			if (scp > 0) {
				scp = ct.toLowerCase().indexOf("charset=", scp);
				if (scp >= 0) {
					ct = ct.substring(scp + 8);
					scp = ct.indexOf(' ');
					if (scp > 0) {
                        ct = ct.substring(0, scp);
                    }
					scp = ct.indexOf(';');
					if (scp > 0) {
                        ct = ct.substring(0, scp);
                    }
					int l = ct.length();
					if (ct.charAt(0) == '"' && l > 2) {
						return ct.substring(1, l - 1);
					}
					return ct;
				}
			}
		}
		//获取不到时就为空 参考于Tomcat 5.3.0
//		if (charEncoding==null || charEncoding.length()<1) {
//			charEncoding =
//				serve
//					.getServeParameter()
//						.getArgumentString(IGlobalVar.ARG_SERVLET_TRANSFER_ENCODING);
//			if(charEncoding==null || charEncoding.length()<1) {
//				charEncoding = IGlobalVar.ISO88591;
//			}
//		}
		return charEncoding;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:08
	 */
	public void flushBuffer() {}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:13
	 */
	public void resetBuffer() {
		throw new IllegalStateException("The method not implemented");
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:16
	 */
	public int getBufferSize() {
		return 0;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:19
	 */
	public void setBufferSize(int size) {}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:27
	 */
	public boolean isCommitted() {
		return headersWritten;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:32
	 */
	public void reset() throws IllegalStateException {
		if (!isCommitted()) {
			if (outCookies != null) {
                outCookies.clear();
            }
			resHeaderNames.clear();
		} else {
            throw new IllegalStateException(
                    "Header have already been committed.");
        }
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:38
	 */
	public void setLocale(java.util.Locale locale) {
		this.locale = locale;
	}

	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:50
	 */
	public java.util.Locale getLocale() {
		if (locale != null) {
            return locale;
        }
		Enumeration<Locale> e = getLocales();
		if (e.hasMoreElements()) {
            return e.nextElement();
        }
		return Locale.getDefault();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:53
	 */
	@SuppressWarnings("unchecked")
    public Enumeration<Locale> getLocales() {
		String al = getHeader(IGlobalVar.ACCEPT_LANGUAGE);
		TreeSet<LocaleWithWeight> ts = new TreeSet<LocaleWithWeight>();
		if (al != null) {
			// System.err.println("Accept lang:"+al);
			StringTokenizer st = new StringTokenizer(al, ";", false);
			try {
				while (st.hasMoreTokens()) {
					String langs = st.nextToken(";");
					// System.err.println("Langs:"+langs);
					String q = st.nextToken(";=");
					// System.err.println("q:"+q);
					q = st.nextToken("=,");
					// System.err.println("q:"+q);
					float w = 0;
					try {
						w = Float.valueOf(q).floatValue();
					} catch (NumberFormatException nfe) {
					}
					if (w > 0) {
						StringTokenizer lst = new StringTokenizer(langs, ", ",
								false);
						while (lst.hasMoreTokens()) {
							String lan = lst.nextToken();
							int di = lan.indexOf('-');
							if (di < 0) {
                                ts.add(new LocaleWithWeight(new Locale(lan
                                        .trim()), w));
                            } else {
                                ts.add(new LocaleWithWeight(
                                        new Locale(lan.substring(0, di), lan
                                                .substring(di + 1).trim()
                                                .toUpperCase()), w));
                            }
						}
					}
				}
			} catch (NoSuchElementException ncee) {
				// can't parse
			}
		}
		if (ts.size() == 0) {
            ts.add(new LocaleWithWeight(Locale.getDefault(), 1));
        }
		return new AcceptLocaleEnumeration(ts);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:00
	 */
	public void setCharacterEncoding(String _enc) {
		charEncoding = _enc;
		synchronized (this) {
			if (unCodeReqUriPath!=null && _enc!=null) {
				//重新进行解码
				reqUriPath = unCodeReqUriPath;
				try {
					reqUriPath = new String(reqUriPath.getBytes(),_enc);
					int qmark = reqUriPath.indexOf('?');
					if (qmark > -1) {
						reqQuery = reqUriPath.substring(qmark + 1);
						reqUriPath = URLDecoder.decode(reqUriPath.substring(0, qmark),_enc);
					} else {
						reqUriPath = URLDecoder.decode(reqUriPath,_enc);
					}
				}catch(Exception e) {}
			}
			formParameters = null;
		}
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:03
	 */
	public void addDateHeader(String header, long date) {
		addHeader(header, expdatefmt.format(new Date(date)));
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:06
	 */
	public void addHeader(String header, String value) {
		header = header.trim();
		Object o = resHeaderNames.get(header);
		if (o == null) {
            setHeader(header, value);
        } else {
			if (o instanceof String[]) {
				String[] oldVal = (String[]) o;
				String[] newVal = new String[oldVal.length + 1];
				System.arraycopy(oldVal, 0, newVal, 0, oldVal.length);
				newVal[oldVal.length] = value;
				resHeaderNames.put(header, newVal);
			} else if (o instanceof String) {
				String[] newVal = new String[2];
				newVal[0] = (String) o;
				newVal[1] = value;
				resHeaderNames.put(header, newVal);
			} else {
                throw new RuntimeException("Invalid content of header hash - "
                        + o.getClass().getName());
            }
		}
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:11
	 */
	public void addIntHeader(String header, int value) {
		addHeader(header, Integer.toString(value));
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:13
	 */
	public RequestDispatcher getRequestDispatcher(String urlpath) {
		// new Exception("!!!getRequestDispatcher orig "+urlpath+" null").printStackTrace();
		return null; // we don't provide resource dispatching in this way
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:22
	 */
	public boolean isSecure() {
		return "https".equals(getScheme());
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:24
	 */
	public void removeAttribute(String name) {
		attributes.remove(name);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:30
	 */
	public String getContextPath() {
		return serve.getContextPath();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:34
	 */
	/*
	public Enumeration<String> getHeaders(String header) {
		Vector result = new Vector();
		int i = -1;
		while ((i = reqHeaderNames.indexOf(header, i + 1)) >= 0)
			result.addElement(reqHeaderValues.elementAt(i));
		return result.elements();
	}
	*/

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:37
	 */
	public java.security.Principal getUserPrincipal() {
		return null;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:41
	 */
	public boolean isUserInRole(String user) {
		return false;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:47
	 */
	public synchronized java.util.Map<String,String[]> getParameterMap() {
		if (formParameters == null) {
            getParameterNames();
        }
		return formParameters;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:51
	 */
	public void addCookie(Cookie cookie) {
		if (outCookies == null) {
            outCookies = new Vector<Cookie>();
        }

		outCookies.addElement(cookie);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:00
	 */
	public boolean containsHeader(String name) {
		return resHeaderNames.contains(name);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:06
	 */
	public String encodeURL(String url) {
		int uop = url.indexOf(IGlobalVar.SESSION_URL_NAME);
		if (uop > 0) {
            url = url.substring(0, uop);
        }
		if (sessionValue == null || isRequestedSessionIdFromCookie()) {
            return url;
        }
		//try {
		//URL urlObj = new URL(url);
		int ehp = url.indexOf('/');
		if (ehp < 0) {
            ehp = url.indexOf('?');
        }
		if (ehp < 0) {
            ehp = url.indexOf('#');
        }
		if (ehp < 0) {
            ehp = url.length();
        }
		if (url.regionMatches(true, 0, getRequestURL().toString(), 0, ehp) == false) {
            return url;
        }
		//} catch (MalformedURLException e) {
		//}

		return url + IGlobalVar.SESSION_URL_NAME + sessionValue;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:11
	 */
	public String encodeRedirectURL(String url) {
		return encodeURL(url);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:15
	 */
	public int getRemotePort() {
		return getServerPort();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:20
	 */
	public String getLocalName() {
		InetAddress ia = socket/* serve.serverSocket */.getInetAddress();
		return ia == null ? null : ia.getHostAddress();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:25
	 */
	public String getLocalAddr() {
		InetAddress ia = /* serve.serverSocket */socket.getInetAddress();
		return ia == null ? null : ia.getCanonicalHostName();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:30
	 */
	public int getLocalPort() {
		return getServerPort();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:42:16
	 */
	public void setStatus(int resCode, String resMessage) {
		// if (this.resCode > 0 && this.resCode != SC_OK)
		// throw new IllegalStateException("Result code "+this.resCode+" was
		// already set.");
		this.resCode = resCode;
		this.resMessage = resMessage;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:42:39
	 */
	public void setHeader(String header, String value) {
		header = header.trim(); // normilize header
		if (value == null) {
            resHeaderNames.remove(header);
        } else {
			resHeaderNames.put(header, value);
		}
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:42:44
	 */
	public void setIntHeader(String header, int value) {
		setHeader(header, Integer.toString(value));
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:42:48
	 * @param header 母鸡
	 * @param value 母鸡
	 */
	public void setLongHeader(String header, long value) {
		setHeader(header, Long.toString(value));
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:43:00
	 */
	public void setDateHeader(String header, long value) {
		try {
			setHeader(header, expdatefmt.format(value<1?new Date():new Date(value)));
		}catch(Exception e) {}
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:43:04
	 * @throws IOException 执行发生异常
	 */
    protected void writeHeaders() throws IOException {
		synchronized (this) {
			if (headersWritten) {
				return;
			}
			headersWritten = true;
		}
		if (reqMime) {
			boolean chunked_out = false;
			boolean wasContentLen = false;
			if(resMessage!=null){
				if (resMessage.length() < 256) {
					out.println(reqProtocol + " " + resCode + " "
							+ resMessage.replace('\r', '/').replace('\n', '/'));
				}else {
					out.println(reqProtocol
							+ " "
							+ resCode
							+ " "
							+ resMessage.substring(0, 255).replace('\r', '/')
									.replace('\n', '/'));
				}
			}
			Enumeration<String> he = resHeaderNames.keys();
			while (he.hasMoreElements()) {
				String name = he.nextElement();
				Object o = resHeaderNames.get(name);
				if (o instanceof String) {
					String value = (String) o;
					if (value != null) {// just in case
						out.println(name + ": " + value);
						if (wasContentLen == false) {
                            if (IGlobalVar.CONTENTLENGTH.equals(name)) {
                                try {
                                    wasContentLen = Long.parseLong(value) > 0;
                                } catch (NumberFormatException nfe) {
                                }
                            }
                        }
						if (chunked_out == false) {
                            if (IGlobalVar.TRANSFERENCODING.equals(name)
                                    && IGlobalVar.CHUNKED.equals(value)) {
                                chunked_out = true;
                            }
                        }
					}
				} else if (o instanceof String[]) {
					String[] values = (String[]) o;
					out.println(name + ": " + values[0]);
					for (int i = 0; i < values.length; i++) {
						out.print("," + values[i]);
					}
					out.println();
				}
			}
			StringBuffer sb = null;
			Cookie cc = null;
			// add session cookie
			if (sessionValue != null) {
				cc = new Cookie(serve.getSessionCookieName(), sessionValue);
        //设置会话安全
        cc.setSecure(true);
        cc.setHttpOnly(true);
				if (serve.getSessionTimeOut() < 0) {
          cc.setMaxAge(Math.abs(serve.getSessionTimeOut()) * 60);
        }
				addCookie(cc);
			}

			// how to remove a cookie
			// cc = new Cookie(cookieName, "");
			// cc.setMaxAge(0);
			//
			for (int i = 0; outCookies != null && i < outCookies.size(); i++) {
				if (sb == null) {
					sb = new StringBuffer(IGlobalVar.SETCOOKIE + ": ");
				}else {
					// sb.append(',');
					sb.append("\r\n" + IGlobalVar.SETCOOKIE + ": "); // for IE not
				}
				// understanding the
				// standard
				cc = outCookies.elementAt(i);
				sb.append(cc.getName());
				sb.append('=');
				sb.append(cc.getValue());
				if (cc.getComment() != null) {
					sb.append("; Comment=" + cc.getComment());
				}
				if (cc.getDomain() != null) {
					sb.append("; domain=" + cc.getDomain());
				}

				if (cc.getMaxAge() >= 0) {
					sb.append("; expires=");
					sb.append(expdatefmt.format(new Date(System
							.currentTimeMillis()
							+ 1000 * cc.getMaxAge())));
				}
				if (cc.getPath() == null) {
					sb.append("; Path=/");
				}else {
					sb.append("; Path=" + cc.getPath());
				}
				if (cc.getSecure()) {
					sb.append("; Secure");
				}
        if(cc.isHttpOnly()){
          sb.append("; HttpOnly");
        }
				if (cc.getVersion() > 0) {
					sb.append("; Version=" + cc.getVersion());
				}
			}
			if (sb != null) {
				out.println(sb.toString());
				// System.err.println("We sent cookies: "+sb);
			}
			if (wasContentLen == false && chunked_out == false
					&& serve.isKeepAlive() && keepAlive) {
				out.println(IGlobalVar.TRANSFERENCODING + ": "
						+ IGlobalVar.CHUNKED);
				chunked_out = true;
			}
			out.println("");
			out.flush();
			((ServeOutputStream) out).setChunked(chunked_out);
		}
	}


	/**
	 * @author 刘虻
	 * 2008-7-9上午02:43:42
	 * @param set
	 */
    public void setInInclude(boolean set) {
		((ServeOutputStream) out).setInInclude(set);
	}

	/**
	 * 发送错误信息到页面
	 * @author 刘虻
	 * 2008-7-9上午02:43:45
	 * @param e 异常
	 * @throws IOException 执行发生异常
	 */
	protected void realSendError(Exception e) throws IOException {
		if (isCommitted()) {
            throw new IllegalStateException(
                    "Can not send error, headers have been already written");
        }
		setContentType("text/html");
		StringBuffer sb = new StringBuffer(100);
		int lsp = resMessage.indexOf('\n');
		sb.append("<HTML><HEAD>").append(
				"<TITLE>" + resCode + " "
						+ (lsp < 0 ? resMessage : resMessage.substring(0, lsp))
						+ "</TITLE>").append(
				"</HEAD><BODY " + IGlobalVar.BGCOLOR).append(
				"><H2>" + resCode + " "
						+ (lsp < 0 ? resMessage : resMessage.substring(0, lsp))
						+ "</H2>");
		if (lsp > 0 || e!=null) {
            sb.append("<PRE>").append(
                    StringUtil.htmlEncode(((lsp>0)?resMessage.substring(lsp):"")+getExceptionInfo(e), false)).append(
                    "</PRE>");
        }
		sb.append("<HR>");
		Identification.writeAddress(sb);
		sb.append("</BODY></HTML>");
		setContentLength(sb.length());
		out.print(sb.toString());
		out.flush();
		out.close();
	}

	
	/**
	 * 解析提交参数
	 * @author 刘虻
	 * 2008-7-1下午01:10:36
	 * @param result 参数容器
	 * @param query 提交参数字符串
	 * @param encoding 参数编码
	 * @return 参数容器
	 */
	protected void parseQueryString(Map<String,String[]> result,String query,String encoding) {
		StringTokenizer st = new StringTokenizer(query, "&");
		while (st.hasMoreTokens()) {
			String pair = st.nextToken();
			int ep = pair.indexOf('=');
			String key = ep > 0 ? pair.substring(0, ep) : pair;
			String value = ep > 0 ? pair.substring(ep + 1) : null;
			try {
				key = /* URLDecoder. */StringUtil.decode(key,encoding);
				if (value != null) {
					value = /* URLDecoder. */StringUtil.decode(value,encoding);
				}
			} catch (UnsupportedEncodingException uee) {}
			String[] values = result.get(key);
			String[] newValues;
			if (values == null) {
				newValues = new String[1];
				newValues[0] = value;
			} else {
				newValues = new String[values.length + 1];
				System.arraycopy(values, 0, newValues, 0, values.length);
				newValues[values.length] = value;
			}
			result.put(key, newValues);
		}
	}

	/**
	 * 解析提交参数
	 * @author 刘虻
	 * 2008-7-9上午07:42:55
	 * @param res 参数容器
	 * @param len  参数信息长度
	 * @param is 参数信息流
	 * @param encoding 参数编码
	 * @param cachedStream 缓存
	 * @throws IOException 执行发生异常
	 */
	protected void parsePostData(Map<String,String[]> res,long len, InputStream is, String encoding, String[] cachedStream)
			throws IOException {
		byte[] buf = new byte[(int) len];
		int fp = 0;
		while (fp < len) {
			int c = is.read(buf, fp, buf.length - fp);
			if (c < 0) {
                break;
            }
			fp += c;
		}
		if (cachedStream != null && cachedStream.length > 0) {
			//parseQueryString(res,cachedStream[0] = new String(buf, 0, fp, ISO_8859_1), encoding);
			parseQueryString(res,cachedStream[0] = new String(buf, 0, fp, encoding), encoding);
		}else {
			//parseQueryString(res,new String(buf, 0, fp, ISO_8859_1), encoding);
			parseQueryString(res,new String(buf, 0, fp, encoding), encoding);
		}
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:44:05
	 */
	public String encodeUrl(String url) {
		return encodeURL(url);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:44:12
	 */
	public String encodeRedirectUrl(String url) {
		return encodeRedirectURL(url);
	}
}